/////////////
// DEFINES //
/////////////
#define NUM_LIGHTS 4


/////////////
// GLOBALS //
/////////////
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
Texture2D shaderTexture;

float4 diffuseColor[NUM_LIGHTS];
float3 lightPosition[NUM_LIGHTS];
float num_lights;
float issun;
float distance1;
float distance2;
float distance3;
float distance4;
///////////////////
// SAMPLE STATES //
///////////////////
SamplerState SampleType
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};


//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
    float3 lightPos1 : TEXCOORD1;
    float3 lightPos2 : TEXCOORD2;
    float3 lightPos3 : TEXCOORD3;
    float3 lightPos4 : TEXCOORD4;
};

////////////////////////////////////////////////////////////////////////////////
// Functions
////////////////////////////////////////////////////////////////////////////////
float calcAttenuation(float objectdistance, float range)
{
    float atten = 1.0f / ( 0.0 * objectdistance * objectdistance + 0.05 * objectdistance + 1.0 );
 
    // Use the step() intrinsic to clamp light to 
    // zero out of its defined range
    return step(objectdistance, range) * saturate( atten );
}

////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType LightVertexShader(VertexInputType input)
{
    PixelInputType output;
    float4 worldPosition;

    // Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;

    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
    
    // Store the texture coordinates for the pixel shader.
    output.tex = input.tex;
    
    // Calculate the normal vector against the world matrix only.
    output.normal = mul(input.normal, (float3x3)worldMatrix);
	
    // Normalize the normal vector.
    output.normal = normalize(output.normal);

    // Calculate the position of the vertex in the world.
    worldPosition = mul(input.position, worldMatrix);

    // Determine the light positions based on the position of the lights and the position of the vertex in the world.
    output.lightPos1 = lightPosition[0].xyz - worldPosition.xyz;
    output.lightPos2 = lightPosition[1].xyz - worldPosition.xyz;
    output.lightPos3 = lightPosition[2].xyz - worldPosition.xyz;
    output.lightPos4 = lightPosition[3].xyz - worldPosition.xyz;
	
    // Normalize the light position vectors.
    output.lightPos1 = normalize(output.lightPos1);
    output.lightPos2 = normalize(output.lightPos2);
    output.lightPos3 = normalize(output.lightPos3);
    output.lightPos4 = normalize(output.lightPos4);

    return output;
}


////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 LightPixelShader(PixelInputType input) : SV_Target
{
    float4 textureColor;
    float lightIntensity1, lightIntensity2, lightIntensity3, lightIntensity4;
    float4 color, color1, color2, color3, color4;

    // Calculate the different amounts of light on this pixel based on the positions of the lights.
    lightIntensity1 = saturate(dot(input.normal, input.lightPos1));
    lightIntensity2 = saturate(dot(input.normal, input.lightPos2));
    lightIntensity3 = saturate(dot(input.normal, input.lightPos3));
    lightIntensity4 = saturate(dot(input.normal, input.lightPos4));
	
    // Determine the diffuse color amount of each of the four lights. and multiply this by attenuation
    color1 = diffuseColor[0] * lightIntensity1 * calcAttenuation(distance1, 1000.0);
    color2 = diffuseColor[1] * lightIntensity2 * calcAttenuation(distance2, 1000.0);
    color3 = diffuseColor[2] * lightIntensity3 * calcAttenuation(distance3, 1000.0);
    color4 = diffuseColor[3] * lightIntensity4 * calcAttenuation(distance4, 1000.0);

    // Sample the texture pixel at this location.
    textureColor = shaderTexture.Sample(SampleType, input.tex);
	// Multiply the texture pixel by the combination of all four light colors to get the final result.
	if(issun!=0.0) {
			if(issun==1.0)
				color = diffuseColor[0] * textureColor;
			else if(issun==2.0)
				color = diffuseColor[1] * textureColor;
			else if(issun==3.0)
				color = diffuseColor[2] * textureColor;
			else if(issun==4.0)
				color = diffuseColor[3] * textureColor;
		}
    else
		color = saturate(color1 + color2 + color3 + color4) * textureColor;
	
    return color;
}



////////////////////////////////////////////////////////////////////////////////
// Technique
////////////////////////////////////////////////////////////////////////////////
technique10 LightTechnique
{
    pass pass0
    {
        SetVertexShader(CompileShader(vs_4_0, LightVertexShader()));
        SetPixelShader(CompileShader(ps_4_0, LightPixelShader()));
        SetGeometryShader(NULL);
    }
}

